package com.glsc.ngateway.opmanage.service.other;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.glsc.ngateway.common.api.platform.dto.other.*;
import com.glsc.ngateway.common.base.domain.mysql.gateway.other.*;
import com.glsc.ngateway.common.base.domainmapper.TradeSeatFeesMapper;
import com.glsc.ngateway.common.base.repo.mysql.gateway.other.*;
import com.glsc.ngateway.opmanage.dto.TradeSeatFeesEmailDto;
import com.glsc.ngateway.opmanage.dto.TradeSeatFeesEmailMonthDto;
import com.glsc.ngateway.opmanage.service.MailService;
import com.glsc.ngateway.opmanage.utils.DateUtils;
import com.glsc.ngateway.opmanage.utils.SpecificationUtil;
import com.glsc.ngateway.opmanage.utils.report.ReportFileConfigEnum;
import com.glsc.ngateway.opmanage.utils.report.ReportFileUtil;
import com.glsc.ngateway.opmanage.utils.report.ReportUploadContext;
import com.google.common.collect.Lists;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.http.entity.ContentType;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.*;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author liwei
 * 交易单元费用预估
 */
@Service
@Slf4j
public class TradeSeatFeesService {
    private static String DATE_YYYY_MM_DD = "yyyy-MM-dd";
    private static String DATE_YYYY_MM = "yyyyMM";

    @Value("${tradeSeat.fileLocation.sh}")
    private String shTradeSeatFileLocation;

    @Value("${tradeSeat.fileLocation.sz}")
    private String szTradeSeatFileLocation;

    @Resource
    private TradeSeatFeesRepository tradeSeatFeesRepository;

    @Resource
    private TradeSeatFlowSpeedRepository tradeSeatFlowSpeedRepository;

    @Resource
    private TradeSeatFileUploadLogRepository tradeSeatFileUploadLogRepository;

    @Resource
    private TradeSeatRentService tradeSeatRentService;

    @Resource
    private TradeSeatFeesItemRepository tradeSeatFeesItemRepository;

    @Resource
    private TradeSeatFeesLogRepository tradeSeatFeesLogRepository;

    @Resource
    private MailService mailService;

    /**
     * 分页查询
     *
     * @param tradeSeatMarket 交易所
     * @param tradeSeatCode   交易单元号
     * @param beginDate       查询起始日期
     * @param endDate         查询结束日期
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Page<TradeSeatFeesDto> findPage(String tradeSeatMarket, String tradeSeatCode, String beginDate, String endDate, int pageNo, int pageSize) {
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "dataDate";
        //Assert.isTrue(StringUtils.isNotEmpty(tradeSeatMarket), "交易市场不可为空");
        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);

        Map<String, Object> param = new HashMap<>();
        if (StrUtil.isNotEmpty(tradeSeatCode)) {
            param.put("LIKE_tradeSeatCode", tradeSeatCode);
        }
        if (StrUtil.isNotEmpty(tradeSeatMarket)) {
            param.put("EQ_tradeSeatMarket", tradeSeatMarket);
        }

        if (StrUtil.isNotEmpty(beginDate)) {
            String begin = convertBeginDate(tradeSeatMarket, beginDate);
            param.put("GTE_dataDate", begin);
        }

        if (StrUtil.isNotEmpty(endDate)) {
            String end = convertEndDate(tradeSeatMarket, endDate);
            param.put("LGTE_dataDate", end);
        }

        Page<TradeSeatFees> ret = tradeSeatFeesRepository.findAll(SpecificationUtil.buildSpecification(param, TradeSeatFees.class), pageable);
        //匹配流速
        Page<TradeSeatFeesDto> tradeSeatFeesDtos = domainToDto(ret, pageable);
        if (CollectionUtil.isNotEmpty(ret.getContent())) {
            List<String> codeList = ret.getContent().stream().map(TradeSeatFees::getTradeSeatCode).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(codeList)) {
                List<TradeSeatFlowSpeed> tradeSeatFlowSpeeds = tradeSeatFlowSpeedRepository.listByTradeSeatCode(codeList);
                if (CollectionUtil.isNotEmpty(tradeSeatFlowSpeeds)) {
                    Map<String, TradeSeatFlowSpeed> flowSpeedMap = tradeSeatFlowSpeeds.stream().collect(Collectors.toMap(TradeSeatFlowSpeed::getTradeSeatCode, e -> e, (i, j) -> j));
                    for (TradeSeatFeesDto e : tradeSeatFeesDtos.getContent()) {
                        TradeSeatFlowSpeed speed = flowSpeedMap.get(e.getTradeSeatCode());
                        if (Objects.nonNull(speed)) {
                            e.setFlowSpeedWeight(speed.getFlowSpeedWeight());
                        }
                    }
                }
            }
        }
        //计算各项费用
        if (CollectionUtil.isNotEmpty(tradeSeatFeesDtos.getContent())) {
            tradeSeatFeesDtos.getContent().forEach(res -> calculateFeesItemNew(res.getTradeSeatMarket(), res));
        }
        return tradeSeatFeesDtos;
    }

    /**
     * 新费用预估算法
     *
     * @param
     */
    private void calculateFeesItemNew(String tradeSeatMarket, TradeSeatFeesDto res) {
        long days = LocalDateTimeUtil.between(res.getChargeBeginDate(), res.getChargeEndDate(), ChronoUnit.DAYS) + 1;

        //计算交易单元使用费  交易单元使用费=30000/365*计费周期起始日至T日的自然天数
        BigDecimal useFees = BigDecimal.valueOf(30000).multiply(BigDecimal.valueOf(days)).divide(BigDecimal.valueOf(365), 4, BigDecimal.ROUND_HALF_UP).setScale(2, BigDecimal.ROUND_HALF_UP);
        res.setUseFees(useFees);

        //计算流量费  流量费=截止T日的交易类报盘笔数*0.1+非交易类报盘笔数*0.01
        int tradingOfferYearAmount = res.getTradingOfferYearAmount();
        int noneTradingOfferYearAmount = res.getNoneTradingOfferYearAmount();
        BigDecimal flowFees = BigDecimal.valueOf(tradingOfferYearAmount).multiply(BigDecimal.valueOf(0.1)).add(BigDecimal.valueOf(noneTradingOfferYearAmount).multiply(BigDecimal.valueOf(0.01)))
                .setScale(2, BigDecimal.ROUND_HALF_UP);
        res.setFlowFees(flowFees);

        //计算流速费  流速费=流速*10000（上海）/365*计费周期起始日至T日的天数 ； 流速费=流速*9600（深圳）/365*计费周期起始日至T日的天数
        BigDecimal flowSpeedFees = null;
        BigDecimal flowSpeedWeight = res.getFlowSpeedWeight();
        if (Objects.isNull(flowSpeedWeight)) {
            flowSpeedWeight = BigDecimal.ZERO;
        }
        if ("sh".equals(tradeSeatMarket)) {
            flowSpeedFees = (flowSpeedWeight).multiply(BigDecimal.valueOf(10000).multiply(BigDecimal.valueOf(days)).divide(BigDecimal.valueOf(365), 4, BigDecimal.ROUND_HALF_UP))
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
        } else if ("sz".equals(tradeSeatMarket)) {
            flowSpeedFees = (flowSpeedWeight).multiply(BigDecimal.valueOf(9600).multiply(BigDecimal.valueOf(days)).divide(BigDecimal.valueOf(365), 4, BigDecimal.ROUND_HALF_UP))
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        res.setFlowSpeedFees(flowSpeedFees);

        //当前交易单元年费  预估当前交易单元年费=交易单元使用费+流量费+流速费
        res.setAnnualFees(useFees.add(flowFees).add(flowSpeedFees));
    }


    /**
     * 交易单元流速导入
     *
     * @param file
     * @return
     * @throws IOException
     */
    @Transactional
    public ReportUploadContext<TradeSeatFlowSpeedImportDto, String> upload(MultipartFile file) throws IOException {
        ReportUploadContext<TradeSeatFlowSpeedImportDto, String> context = ReportUploadContext.<TradeSeatFlowSpeedImportDto, String>builder()
                .config(ReportFileConfigEnum.TRADE_SEAT_FLOW_SPEED_IMPORT)
                .file(file)
                .build();
        ReportFileUtil.readSingleExcel(context);
        //全部检查通过后添加或修改数据
        List<TradeSeatFlowSpeed> resList = Lists.newArrayList();
        if (context.isCheckPass()) {
            for (TradeSeatFlowSpeedImportDto re : context.getReadRes()) {
                resList.add(TradeSeatFlowSpeed.builder().createTime(LocalDateTime.now()).flowSpeedWeight(re.getFlowSpeedWeight()).status(1)
                        .tradeSeatCode(re.getTradeSeatCode()).tradeSeatMarket(null).build());
            }

            List<TradeSeatFlowSpeed> speedList = tradeSeatFlowSpeedRepository.listByTradeSeatCode(resList.stream().map(TradeSeatFlowSpeed::getTradeSeatCode).collect(Collectors.toList()));
            if (CollectionUtil.isNotEmpty(speedList)) {
                tradeSeatFlowSpeedRepository.deleteByTradeSeatCode(speedList.stream().map(TradeSeatFlowSpeed::getTradeSeatCode).collect(Collectors.toList()));
            }
            tradeSeatFlowSpeedRepository.saveAll(resList);
        }
        return context;
    }

    /**
     * 分页查询流速权信息
     *
     * @param tradeSeatCode
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Page<TradeSeatSpeedFlowDto> findFlowSpeedPage(String tradeSeatCode, int pageNo, int pageSize) {
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "tradeSeatFlowSpeedId";

        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);

        Map<String, Object> param = new HashMap<>();
        if (StrUtil.isNotEmpty(tradeSeatCode)) {
            param.put("LIKE_tradeSeatCode", tradeSeatCode);
        }

        Page<TradeSeatFlowSpeed> ret = tradeSeatFlowSpeedRepository.findAll(SpecificationUtil.buildSpecification(param, TradeSeatFlowSpeed.class), pageable);
        List<TradeSeatSpeedFlowDto> contentList = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(ret.getContent())) {
            for (TradeSeatFlowSpeed speed : ret.getContent()) {
                contentList.add(TradeSeatSpeedFlowDto.builder().createTime(speed.getCreateTime()).tradeSeatCode(speed.getTradeSeatCode()).flowSpeedWeight(speed.getFlowSpeedWeight()).build());
            }
        }
        return new PageImpl(contentList, pageable, ret.getTotalElements());
    }

    //todo 由于交易所修改交易单元年费计费周期制度，暂时过滤这些资管子的交易单元，后续去掉
    private List<String> tradeSeatFilter() {
        List<String> resList = Lists.newArrayList();
        //上证
        resList.add("25823");
        resList.add("27876");
        resList.add("33311");
        resList.add("51165");

        //深证
        resList.add("393702");
        resList.add("399599");
        resList.add("013318");
        return resList;
    }


    // 选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()方法 。

    public File transferToFile(MultipartFile multipartFile) {
        File file = null;
        try {
            String originalFilename = multipartFile.getOriginalFilename();
            String[] filename = originalFilename.split("\\.");
            file = File.createTempFile(filename[0], filename[1]);
            multipartFile.transferTo(file);
            file.deleteOnExit();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }


    /**
     * 读取上海交易单元excel信息
     */
//    @PostConstruct
    @Transactional
    //@XxlJob("tradeSeatFeesService_readShTreadSeatInfo")
    public String readShTreadSeatInfo(MultipartFile multipartFile) {
//        File file = new File(shTradeSeatFileLocation);
//        File[] files = file.listFiles();
//        if (null == files || files.length == 0) {
//            log.info("未查询到可以上传的上海市场交易单元excel信息 ");
//            return "未查询到可以上传的上海市场交易单元excel信息";
//        }

        File[] files = new File[1];
        files[0] = transferToFile(multipartFile);

        List<String> fileNameList = Lists.newArrayList();
        for (File localFile : files) {
            if (localFile.isFile()) {
                fileNameList.add(localFile.getName());
            }
        }
        List<TradeSeatFileUploadLog> shFileLogList = tradeSeatFileUploadLogRepository.listTradeSeatFeesDto(fileNameList, "sh");
        List<String> savedNameList = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(shFileLogList)) {
            savedNameList = shFileLogList.stream().map(TradeSeatFileUploadLog::getFileName).collect(Collectors.toList());
        }
        List<TradeSeatFees> resList = Lists.newArrayList();
        List<TradeSeatFeesItem> itemResList = Lists.newArrayList();
        for (File localFile : files) {
            if (!localFile.isFile()) {
                continue;
            }
            if (savedNameList.contains(localFile.getName())) {
                continue;
            }
            ReportUploadContext<TradeSeatFeesShImportDto, String> context = ReportUploadContext.<TradeSeatFeesShImportDto, String>builder()
                    .config(ReportFileConfigEnum.TRADE_SEAT_FEES_SH_IMPORT)
                    .file(convertMultipartFile(localFile))
                    .build();
            try {
                ReportFileUtil.readSingleExcel(context);
            } catch (IOException e) {
                log.error("异常", e);
            }
            //保存文件记录
            tradeSeatFileUploadLogRepository.save(TradeSeatFileUploadLog.builder().createTime(LocalDateTime.now()).fileName(localFile.getName()).tradeSeatMarket("sh").build());
            Map<String, TradeSeatFees> codeDateMap = new HashMap<>();

            String shBeginDate = convertBeginDate("sh", null);
            List<String> seatFilterList = tradeSeatFilter();

            for (TradeSeatFeesShImportDto readRe : context.getReadRes()) {

                //这些交易单元不录入
                if (seatFilterList.contains(readRe.getTradeSeatCode())) {
                    continue;
                }

                if (DateUtil.parse(shBeginDate, DATE_YYYY_MM_DD).isBeforeOrEquals(DateUtil.parse(readRe.getDataDate(), DATE_YYYY_MM))) {
                    TradeSeatFees saved = codeDateMap.get(readRe.getTradeSeatCode());
                    //保存最新的记录
                    if (Objects.isNull(saved) || saved.getDataDate().isBefore(DateUtil.parseLocalDateTime(readRe.getDataDate(), DATE_YYYY_MM))) {
                        //当月需要有数据才更新主表信息


                        //if (readRe.getNoneTradingOfferAmount() != 0 || readRe.getTradingOfferAmount() != 0) {
                        codeDateMap.put(readRe.getTradeSeatCode(), TradeSeatFees.builder().createTime(LocalDateTime.now()).dataDate(DateUtil.parseLocalDateTime(readRe.getDataDate(), DATE_YYYY_MM))
                                .tradeSeatCode(readRe.getTradeSeatCode()).tradeSeatName("").noneTradingOfferAmount(readRe.getNoneTradingOfferAmount())
                                .noneTradingOfferYearAmount(readRe.getNoneTradingOfferYearAmount()).tradeSeatFeesId(readRe.getTradeSeatCode())
                                .tradingOfferAmount(readRe.getTradingOfferAmount()).tradingOfferYearAmount(readRe.getTradingOfferYearAmount()).tradeSeatMarket("sh").status(1)
                                .chargeEndDate(DateUtil.parseLocalDateTime(convertEndDateNew(LocalDateTime.now()), DATE_YYYY_MM_DD)).build());
                        //}
                    }

                    itemResList.add(TradeSeatFeesItem.builder().createTime(LocalDateTime.now()).dataDate(DateUtil.parseLocalDateTime(readRe.getDataDate(), DATE_YYYY_MM))
                            .tradeSeatName("").noneTradingOfferAmount(readRe.getNoneTradingOfferAmount()).noneTradingOfferYearAmount(readRe.getNoneTradingOfferYearAmount())
                            .id(readRe.getTradeSeatCode() + readRe.getDataDate()).tradeSeatCode(readRe.getTradeSeatCode())
                            .tradingOfferAmount(readRe.getTradingOfferAmount()).tradingOfferYearAmount(readRe.getTradingOfferYearAmount()).tradeSeatMarket("sh").build());
                }
            }
            Collection<TradeSeatFees> collection = codeDateMap.values();
            if (CollectionUtil.isNotEmpty(collection)) {
                resList.addAll(collection);
            }
        }
        if (CollectionUtil.isNotEmpty(resList)) {
            Map<String, TradeSeatRent> map = new HashMap();
            Map<String, Object> param = new HashMap<>();
            List<String> tradeCodeList = resList.stream().map(TradeSeatFees::getTradeSeatCode).collect(Collectors.toList());
            param.put("INSTR_tradeSeatCode", String.join(",", tradeCodeList));
            List<TradeSeatRent> list = tradeSeatRentService.findList(param);
            if (CollectionUtil.isNotEmpty(list)) {
                map = list.stream().collect(Collectors.toMap(TradeSeatRent::getTradeSeatCode, e -> e, (i, j) -> j));
            }
            //更新主表信息

            List<TradeSeatFees> saveResList = Lists.newArrayList();
            for (TradeSeatFees tradeSeatFees : resList) {
                TradeSeatRent tradeSeatRent = Objects.isNull(map.get(tradeSeatFees.getTradeSeatCode())) ? new TradeSeatRent() : map.get(tradeSeatFees.getTradeSeatCode());
                tradeSeatFees.setChargeBeginDate(convertBeginLocalDateTime("sh",
                        StringUtils.isNotBlank(tradeSeatRent.getBeginDate()) ? tradeSeatRent.getBeginDate().substring(0, 7) + "-01" : null));
                if (Objects.nonNull(tradeSeatRent)) {
                    if ("0".equals(tradeSeatRent.getState())) {
                        if (StringUtils.isNotBlank(tradeSeatRent.getEndDate())) {
                            if (tradeSeatRent.getEndDate().substring(0, 7).equals(DateUtils.getNowDateString().substring(0, 7))) {
                                saveResList.add(tradeSeatFees);
                            }
                        }
                    } else {
                        saveResList.add(tradeSeatFees);
                    }
                }

            }
            tradeSeatFeesRepository.saveAll(saveResList);

            List<TradeSeatFeesItem> saveItemResList = Lists.newArrayList();
            if (CollectionUtil.isNotEmpty(itemResList)) {
                //更新子表-详情列表
                for (TradeSeatFeesItem tradeSeatFees : itemResList) {
                    TradeSeatRent tradeSeatRent = Objects.isNull(map.get(tradeSeatFees.getTradeSeatCode())) ? new TradeSeatRent() : map.get(tradeSeatFees.getTradeSeatCode());
                    if (Objects.nonNull(tradeSeatRent)) {
                        if ("0".equals(tradeSeatRent.getState())) {
                            if (StringUtils.isNotBlank(tradeSeatRent.getEndDate())) {
                                if (tradeSeatRent.getEndDate().substring(0, 7).equals(DateUtils.getNowDateString().substring(0, 7))) {
                                    saveItemResList.add(tradeSeatFees);
                                }
                            }
                        } else {
                            saveItemResList.add(tradeSeatFees);
                        }
                    }
                }
                tradeSeatFeesItemRepository.saveAll(saveItemResList);
            }
        }
        return "";
    }

    /**
     * 读取深圳交易单元excel信息
     */
//    @XxlJob("tradeSeatFeesService_readSzTreadSeatInfo")
    @Transactional
    public String readSzTreadSeatInfo(MultipartFile multipartFile) {
//        File file = new File(szTradeSeatFileLocation);
//        File[] files = file.listFiles();
//        if (null == files || files.length == 0) {
//            log.info("未查询到可以上传的深圳市场交易单元excel信息 ");
//            return "未查询到可以上传的深圳市场交易单元excel信息";
//        }

        File[] files = new File[1];
        files[0] = transferToFile(multipartFile);

        List<String> fileNames = Lists.newArrayList();
        for (File localFile : files) {
            if (localFile.isFile()) {
                fileNames.add(localFile.getName());
            }
        }
        List<TradeSeatFileUploadLog> szFileLogList = tradeSeatFileUploadLogRepository.listTradeSeatFeesDto(fileNames, "sz");
        List<String> savedNameList = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(szFileLogList)) {
            savedNameList = szFileLogList.stream().map(TradeSeatFileUploadLog::getFileName).collect(Collectors.toList());
        }
        List<TradeSeatFees> resList = Lists.newArrayList();
        List<TradeSeatFeesItem> itemResList = Lists.newArrayList();
        String shBeginDate = convertBeginDate("sz", null);
        for (File localFile : files) {
            if (!localFile.isFile()) {
                continue;
            }

            if (savedNameList.contains(localFile.getName())) {
                continue;
            }
            String dateTime = localFile.getName().replace(".xls", "").replace("深交所交易单元流量统计", "");
            ExcelReader reader = ExcelUtil.getReader(localFile);
            // 获取第一个 sheet，通过索引指定
            reader.setSheet(1);
            // 从第二行开始读取,忽略表头
            List<List<Object>> rows = reader.read(2);

            //保存文件记录
            tradeSeatFileUploadLogRepository.save(TradeSeatFileUploadLog.builder().createTime(LocalDateTime.now()).fileName(localFile.getName()).tradeSeatMarket("sz").build());

            if (CollectionUtil.isEmpty(rows)) {
                continue;
            }

            List<String> seatFilterList = tradeSeatFilter();

            for (List<Object> list : rows) {

                //这些交易单元不录入
                if (seatFilterList.contains(String.valueOf(list.get(0)))) {
                    continue;
                }
                if (DateUtil.parse(shBeginDate, DATE_YYYY_MM_DD).isBeforeOrEquals(DateUtil.parse(dateTime, "yyyyMMdd"))) {
                    //当月有数据才更新主表数据
                    //if (Integer.parseInt(String.valueOf(list.get(4))) != 0
                    //        || Integer.parseInt(String.valueOf(list.get(2))) != 0) {
                    resList.add(TradeSeatFees.builder().createTime(LocalDateTime.now()).dataDate(DateUtil.parseLocalDateTime(dateTime, "yyyyMMdd"))
                            .tradeSeatCode(String.valueOf(list.get(0))).tradeSeatName(String.valueOf(list.get(1)))
                            .noneTradingOfferAmount(null).noneTradingOfferYearAmount(Integer.parseInt(String.valueOf(list.get(4)))).tradeSeatFeesId(String.valueOf(list.get(0)))
                            .tradingOfferAmount(null).tradingOfferYearAmount(Integer.parseInt(String.valueOf(list.get(2)))).tradeSeatMarket("sz").status(1)
                            .chargeEndDate(DateUtil.parseLocalDateTime(convertEndDateNew(LocalDateTime.now()), DATE_YYYY_MM_DD)).build());
                    //}

                    itemResList.add(TradeSeatFeesItem.builder().createTime(LocalDateTime.now()).dataDate(DateUtil.parseLocalDateTime(dateTime, "yyyyMMdd"))
                            .tradeSeatCode(String.valueOf(list.get(0))).tradeSeatName(String.valueOf(list.get(1)))
                            .noneTradingOfferAmount(null).noneTradingOfferYearAmount(Integer.parseInt(String.valueOf(list.get(4)))).id(String.valueOf(list.get(0)) + dateTime)
                            .tradingOfferAmount(null).tradingOfferYearAmount(Integer.parseInt(String.valueOf(list.get(2)))).tradeSeatMarket("sz").build());
                }
            }
        }
        if (CollectionUtil.isNotEmpty(resList)) {
            Map<String, Object> param = new HashMap<>();
            List<String> tradeCodeList = resList.stream().map(TradeSeatFees::getTradeSeatCode).collect(Collectors.toList());
            param.put("INSTR_tradeSeatCode", String.join(",", tradeCodeList));
            List<TradeSeatRent> list = tradeSeatRentService.findList(param);
            Map<String, TradeSeatRent> map = new HashMap();
            if (CollectionUtil.isNotEmpty(list)) {
                map = list.stream().collect(Collectors.toMap(TradeSeatRent::getTradeSeatCode, e -> e, (i, j) -> j));
            }
            //更新主表信息

            List<TradeSeatFees> saveResList = Lists.newArrayList();
            for (TradeSeatFees tradeSeatFees : resList) {
                TradeSeatRent tradeSeatRent = Objects.isNull(map.get(tradeSeatFees.getTradeSeatCode())) ? new TradeSeatRent() : map.get(tradeSeatFees.getTradeSeatCode());
                tradeSeatFees.setChargeBeginDate(convertBeginLocalDateTime("sz",
                        StringUtils.isNotBlank(tradeSeatRent.getBeginDate()) ? tradeSeatRent.getBeginDate().substring(0, 7) + "-01" : null));

                if (Objects.nonNull(tradeSeatRent)) {
                    if ("0".equals(tradeSeatRent.getState())) {
                        if (StringUtils.isNotBlank(tradeSeatRent.getEndDate())) {
                            if (tradeSeatRent.getEndDate().substring(0, 7).equals(DateUtils.getNowDateString().substring(0, 7))) {
                                saveResList.add(tradeSeatFees);
                            }
                        }
                    } else {
                        saveResList.add(tradeSeatFees);
                    }
                }
            }
            tradeSeatFeesRepository.saveAll(saveResList);
            if (CollectionUtil.isNotEmpty(itemResList)) {
                //更新子表-详情列表
                List<TradeSeatFeesItem> saveItemResList = Lists.newArrayList();

                for (TradeSeatFeesItem tradeSeatFees : itemResList) {
                    TradeSeatRent tradeSeatRent = Objects.isNull(map.get(tradeSeatFees.getTradeSeatCode())) ? new TradeSeatRent() : map.get(tradeSeatFees.getTradeSeatCode());
                    if (Objects.nonNull(tradeSeatRent)) {
                        if ("0".equals(tradeSeatRent.getState())) {
                            if (StringUtils.isNotBlank(tradeSeatRent.getEndDate())) {
                                if (tradeSeatRent.getEndDate().substring(0, 7).equals(DateUtils.getNowDateString().substring(0, 7))) {
                                    saveItemResList.add(tradeSeatFees);
                                }
                            }
                        } else {
                            saveItemResList.add(tradeSeatFees);
                        }
                    }
                }
                tradeSeatFeesItemRepository.saveAll(saveItemResList);
            }
        }
        return "";
    }

    /**
     * 交易单元费用跨年处理 - 定时任务
     * 已停用的交易单元结算  - 定时任务
     */
    //@PostConstruct
    @XxlJob("tradeSeatFeesService_updateFeesByDateLine")
    public String updateFeesByDateLine() {
        tradeSeatSettlement();
        dealNextTradeFeesData();
        return "";
    }


    public Page<TradeSeatFeesItem> findItemPage(String tradeSeatCode, int pageNo, int pageSize) {
        Assert.notNull(tradeSeatCode, "交易单元编号不可为空");
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "dataDate";
        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);

        Map<String, Object> param = new HashMap<>();
        if (StrUtil.isNotEmpty(tradeSeatCode)) {
            param.put("LIKE_tradeSeatCode", tradeSeatCode);
        }
        Page<TradeSeatFeesItem> ret = tradeSeatFeesItemRepository.findAll(SpecificationUtil.buildSpecification(param, TradeSeatFeesItem.class), pageable);
        return ret;
    }


    public Page<TradeSeatFeesLog> findLogPage(String tradeSeatCode, int pageNo, int pageSize) {
        Assert.notNull(tradeSeatCode, "交易单元编号不可为空");
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "dataDate";
        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);

        Map<String, Object> param = new HashMap<>();
        if (StrUtil.isNotEmpty(tradeSeatCode)) {
            param.put("LIKE_tradeSeatCode", tradeSeatCode);
        }
        Page<TradeSeatFeesLog> ret = tradeSeatFeesLogRepository.findAll(SpecificationUtil.buildSpecification(param, TradeSeatFeesLog.class), pageable);
        return ret;
    }


    /**
     * 交易单元停用和更新处理
     */
    public void dealDisableTradeSeat(String beforeState, String afterState, String tradeSeatCode, String beginDate, String endDate, String beginDate2) {
        List<TradeSeatFees> fees = this.tradeSeatFeesRepository.findAll(Example.of(TradeSeatFees.builder().tradeSeatFeesId(tradeSeatCode).build()));
        if (CollectionUtil.isEmpty(fees)) {
            return;
        }
        TradeSeatFees tradeSeatFees = fees.get(0);
        //停用交易单元操作
        if (afterState.equals("0") && beforeState.equals("1")) {
            TradeSeatFeesLog feesLog = null;
            try {
                feesLog = TradeSeatFeesLog.builder().tradeSeatCode(tradeSeatCode)
                        .chargeBeginDate(convertBeginLocalDateTime(tradeSeatFees.getTradeSeatMarket(), beginDate))
                        .chargeEndDate(LocalDateTimeUtil.parse(endDate, DATE_YYYY_MM_DD))
                        .tradeSeatMarket(tradeSeatFees.getTradeSeatMarket())
                        .state("0").build();
                if (StringUtils.isNotBlank(endDate)) {
                    tradeSeatFees.setChargeEndDate(LocalDateTimeUtil.parse(endDate, DATE_YYYY_MM_DD));
                }
            } catch (Exception e) {
                feesLog = TradeSeatFeesLog.builder().tradeSeatCode(tradeSeatCode)
                        .chargeBeginDate(null)
                        .chargeEndDate(LocalDateTimeUtil.parse(endDate, DATE_YYYY_MM_DD))
                        .tradeSeatMarket(tradeSeatFees.getTradeSeatMarket())
                        .state("0").memo("交易单元停用异常-未查询到启用时间").build();
            }
            tradeSeatFeesLogRepository.save(feesLog);
        } else if (afterState.equals("1") && beforeState.equals("1")) {
            //更新交易单元起停用时间
            if (StringUtils.isNotBlank(beginDate2)) {
                tradeSeatFees.setChargeBeginDate(convertBeginLocalDateTime(tradeSeatFees.getTradeSeatMarket(), beginDate2));
            }
            if (StringUtils.isNotBlank(endDate)) {
                tradeSeatFees.setChargeEndDate(LocalDateTimeUtil.parse(endDate, DATE_YYYY_MM_DD));
            }
            tradeSeatFeesRepository.save(tradeSeatFees);
        }
    }


    /**
     * 已停用的交易单元结算  - 定时任务
     */
//    @PostConstruct
    public void tradeSeatSettlement() {
        List<TradeSeatFeesLog> feesLogs = tradeSeatFeesLogRepository.findAll(Example.of(TradeSeatFeesLog.builder().state("0").build()));
        if (CollectionUtil.isEmpty(feesLogs)) {
            return;
        }

        for (TradeSeatFeesLog feesLog : feesLogs) {
            List<TradeSeatFees> fees = tradeSeatFeesRepository.findAll(Example.of(TradeSeatFees.builder().tradeSeatFeesId(feesLog.getTradeSeatCode()).build()));
            if (CollectionUtil.isEmpty(fees)) {
                feesLog.setMemo("未查询到响应的交易单元费用预估信息，状态异常任务停止");
                feesLog.setState("1");
                tradeSeatFeesLogRepository.save(feesLog);
                continue;
            }
            TradeSeatFees tradeSeatFees = fees.get(0);
            if (LocalDateTimeUtil.between(feesLog.getChargeEndDate(), tradeSeatFees.getDataDate(), ChronoUnit.MONTHS) == 0) {
                long between = LocalDateTimeUtil.between(tradeSeatFees.getDataDate(), LocalDateTime.now(), ChronoUnit.MONTHS);
                if (between == 1) {
                    TradeSeatFeesDto tradeSeatFeesDto = new TradeSeatFeesDto();
                    BeanUtils.copyProperties(tradeSeatFees, tradeSeatFeesDto);
                    //计算各项费用
                    calculateFeesItemNew(tradeSeatFees.getTradeSeatMarket(), tradeSeatFeesDto);

                    feesLog.setState("1");
                    feesLog.setAnnualFees(tradeSeatFeesDto.getAnnualFees());
                    feesLog.setFlowFees(tradeSeatFeesDto.getFlowFees());
                    feesLog.setFlowSpeedFees(tradeSeatFeesDto.getFlowSpeedFees());
                    feesLog.setUseFees(tradeSeatFeesDto.getUseFees());
                    tradeSeatFeesLogRepository.save(feesLog);
                } else if (between > 1) {
                    feesLog.setState("1");
                    feesLog.setMemo("结算失败，原因：未在规定时间内结算");
                    tradeSeatFeesLogRepository.save(feesLog);
                }

            }
        }
    }

    /**
     * 交易单元费用跨年处理 - 定时任务
     */
    //@PostConstruct
    public void dealNextTradeFeesData() {
        //只在每年的12月1号执行
        if (!DateUtil.format(new Date(), "MM-dd").equals("12-28")) {
            return;
        }
        List<TradeSeatFees> fees = tradeSeatFeesRepository.findAll();
        if (CollectionUtil.isNotEmpty(fees)) {
            for (TradeSeatFees tradeSeatFees : fees) {
                long between = LocalDateTimeUtil.between(tradeSeatFees.getDataDate(), LocalDateTime.now(), ChronoUnit.MONTHS);
                TradeSeatFeesLog feesLog = new TradeSeatFeesLog();
                if (between == 1) {
                    TradeSeatFeesDto tradeSeatFeesDto = new TradeSeatFeesDto();
                    BeanUtils.copyProperties(tradeSeatFees, tradeSeatFeesDto);
                    //计算各项费用
                    calculateFeesItemNew(tradeSeatFees.getTradeSeatMarket(), tradeSeatFeesDto);
                    BeanUtils.copyProperties(tradeSeatFees, feesLog);
                    feesLog.setState("1");
                    feesLog.setAnnualFees(tradeSeatFeesDto.getAnnualFees());
                    feesLog.setFlowFees(tradeSeatFeesDto.getFlowFees());
                    feesLog.setFlowSpeedFees(tradeSeatFeesDto.getFlowSpeedFees());
                    feesLog.setUseFees(tradeSeatFeesDto.getUseFees());
                    feesLog.setMemo("跨计费周期处理");
                    tradeSeatFeesLogRepository.save(feesLog);
                } else if (between > 1) {
                    feesLog.setState("1");
                    feesLog.setMemo("跨计费周期处理失败");
                    tradeSeatFeesLogRepository.save(feesLog);
                }
            }
        }
        tradeSeatFeesRepository.deleteAll();
        tradeSeatFeesItemRepository.deleteAll();
    }

    /**
     * 发送资管子公司交易单元费用预估信息
     */
//    @PostConstruct
    public void amFeeForecastEmail() {
        TradeSeatRent rent = new TradeSeatRent();
        rent.setUseType("3");
        List<TradeSeatRent> list = tradeSeatRentService.findList(rent);

        //查询所有资管子公司的交易单元信息
        if (CollectionUtil.isEmpty(list)) {
            return;
        }
        List<String> tradeSeatCodeList = list.stream().map(TradeSeatRent::getTradeSeatCode).collect(Collectors.toList());

        Map<String, Object> param = new HashMap<>();
        param.put("INSTR_tradeSeatCode", StringUtils.join(tradeSeatCodeList, ","));
        List<TradeSeatFees> seatFeesList = tradeSeatFeesRepository.findAll(SpecificationUtil.buildSpecification(param, TradeSeatFees.class));
        //深交所和上交所的数据分开放在各自的Excel中

        if (CollectionUtil.isEmpty(seatFeesList)) {
            return;
        }
        LocalDateTime preMonth = LocalDateTime.now().minusMonths(1);


        Map<String, Object> shItemParam = new HashMap<>();
        shItemParam.put("INSTR_tradeSeatCode", StringUtils.join(tradeSeatCodeList, ","));
        shItemParam.put("EQ_tradeSeatMarket", "sh");
        //查找上个月第一天到最后一天的所有费用预估详情
        shItemParam.put("GTE_dataDate", DateUtil.format(preMonth.with(TemporalAdjusters.firstDayOfMonth()), DATE_YYYY_MM_DD));
        shItemParam.put("LGTE_dataDate", DateUtil.format(preMonth.with(TemporalAdjusters.lastDayOfMonth()), DATE_YYYY_MM_DD));
        List<TradeSeatFeesItem> shItemsList = tradeSeatFeesItemRepository.findAll(SpecificationUtil.buildSpecification(shItemParam, TradeSeatFeesItem.class));


        Map<String, Object> szItemParam = new HashMap<>();
        szItemParam.put("INSTR_tradeSeatCode", StringUtils.join(tradeSeatCodeList, ","));
        szItemParam.put("EQ_tradeSeatMarket", "sz");
        //查找上个月第一天到最后一天的所有费用预估详情
        szItemParam.put("GTE_dataDate", DateUtil.format(preMonth.minusMonths(1).with(TemporalAdjusters.firstDayOfMonth()), DATE_YYYY_MM_DD));
        szItemParam.put("LGTE_dataDate", DateUtil.format(preMonth.with(TemporalAdjusters.lastDayOfMonth()), DATE_YYYY_MM_DD));
        List<TradeSeatFeesItem> szItemsList = tradeSeatFeesItemRepository.findAll(SpecificationUtil.buildSpecification(szItemParam, TradeSeatFeesItem.class));

        String emailId = sendAmEmail(seatFeesList, shItemsList, szItemsList);
        seatFeesList.forEach(e -> e.setEmailId(emailId));
        tradeSeatFeesRepository.saveAll(seatFeesList);
    }


    @Transactional
    public String sendAmEmail(List<TradeSeatFees> seatFeesList, List<TradeSeatFeesItem> shItemsList, List<TradeSeatFeesItem> sourceSzItemsList) {
        String title = "资管子托管交易单元年费预估";
        String content = "<div style=\"position:relative;left:0;color: #666666; font-size: 14px; font-family: 'Open Sans',Helvetica,Arial,sans-serif;\">\n" +
                "    <div class=\"box-content\" style=\"width: 80%;min-width: 600px;\">\n" +
                "        <div class=\"tips\" style=\"padding:8px;\">\n" +
                "            <div class=\"tips\" style=\"padding:8px;\">\n" +
                "                <p style=\" list-style: 160%; margin: 10px 0;\">资管子各位同事：</p>\n" +
                "                <p style=\" list-style: 160%; margin: 10px 0;\">    根据上海、深圳交易所公布的交易单元申报笔数，运营管理总部预估资管子托管交易单元费用明细，详见附件，包括（1）从本年计费起始日至上月费用汇总数；（2）仅上月费用数据。北京交易所每月不公布交易单元申报笔数。</p>\n" +
                "\t\t\t\t<p style=\" list-style: 160%; margin: 10px 0;\"> 本数据为费用预估值，仅供参考。资管交易单元实际承担金额以交易所实际收费及分摊为准。</p>\n" +
                "\t\t\t\n" +
                "\t   \t\t<p style=\" list-style: 160%; margin: 10px 0;\">联系人肖丹，0510-82833027。</p>\n" +
                "            </div>\n" +
                "            <hr/>\n" +
                "            <div><img src=\"\" border=\"0\"></div>\n" +
                "            <strong><p style=\" list-style: 160%; margin: 10px 0;\">国 联 运 管</p></strong>\n" +
                "            <p style=\" list-style: 160%; margin: 10px 0;\">部门:运营管理总部</p>\n" +
                "            <p style=\" list-style: 160%; margin: 10px 0;\">地址:江苏省无锡市太湖新城金融一街8号 国联金融大厦 707</p>\n" +
                "            <p style=\" list-style: 160%; margin: 10px 0;\">电话:0510-82833027</p>\n" +
                "            <p style=\" list-style: 160%; margin: 10px 0;\">Email:xiaod@glsc.com.cn</p>\n" +
                "        </div>\n" +
                "    </div>\n" +
                "</div>";

        LocalDateTime localDateTime = LocalDateTime.now().minusMonths(1);
        //附件列表
        List<File> attachmentList = Lists.newArrayList();
        //收件人邮箱
        List<String> recvMailList = Lists.newArrayList();
        //目前只发肖丹，后续发资管子
        recvMailList.add("xiaod@glsc.com.cn");

        //资管子发送邮件列表
        recvMailList.add("yiyang@glsc.com.cn");
        recvMailList.add("yuanguo@glsc.com.cn");
        recvMailList.add("liww@glsc.com.cn");

        //获取深交所的交易单元费用预估信息
        List<TradeSeatFees> szFeeList = seatFeesList.stream().filter(e -> "sz".equals(e.getTradeSeatMarket())).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(szFeeList)) {
            List<TradeSeatFeesDto> contentList = TradeSeatFeesMapper.INSTANCE.domain2dto(szFeeList);

            addFlowSpeed(contentList);
            for (TradeSeatFeesDto tradeSeatFeesDto : contentList) {
                calculateFeesItemNew("sz", tradeSeatFeesDto);
            }

            File emailFile = createEmailFile("深交所交易单元费用预估.xlsx", ReportFileConfigEnum.TRADE_SEAT_FEES_EXPORT_AM,
                    convertTradeSeatFeesEmailDto(contentList));
            attachmentList.add(emailFile);
        }

        //获取上交所的交易单元费用预估信息
        List<TradeSeatFees> shFeeList = seatFeesList.stream().filter(e -> "sh".equals(e.getTradeSeatMarket())).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(szFeeList)) {

            List<TradeSeatFeesDto> contentList = TradeSeatFeesMapper.INSTANCE.domain2dto(shFeeList);

            addFlowSpeed(contentList);
            for (TradeSeatFeesDto tradeSeatFeesDto : contentList) {
                calculateFeesItemNew("sh", tradeSeatFeesDto);
            }

            File emailFile = createEmailFile("上交所交易单元费用预估.xlsx", ReportFileConfigEnum.TRADE_SEAT_FEES_EXPORT_AM,
                    convertTradeSeatFeesEmailDto(contentList));
            attachmentList.add(emailFile);
        }

        //生成上交所本月费用预估信息excel
        if (CollectionUtil.isNotEmpty(shItemsList)) {
            List<TradeSeatFeesDto> contentList = TradeSeatFeesMapper.INSTANCE.domain2dto(convertFees4Item(shItemsList));

            addFlowSpeed(contentList);
            for (TradeSeatFeesDto tradeSeatFeesDto : contentList) {
                tradeSeatFeesDto.setChargeBeginDate(localDateTime.with(TemporalAdjusters.firstDayOfMonth()));
                tradeSeatFeesDto.setChargeEndDate(localDateTime.with(TemporalAdjusters.lastDayOfMonth()));

                tradeSeatFeesDto.setTradingOfferYearAmount(tradeSeatFeesDto.getTradingOfferAmount());
                tradeSeatFeesDto.setNoneTradingOfferYearAmount(tradeSeatFeesDto.getNoneTradingOfferAmount());
                calculateFeesItemNew("sh", tradeSeatFeesDto);
            }

            File emailFile = createEmailFile("上交所交易单元费用预估-本月.xlsx", ReportFileConfigEnum.TRADE_SEAT_FEES_EXPORT_AM_MONTH,
                    convertTradeSeatFeesEmailMonthDto(contentList));
            attachmentList.add(emailFile);
        }

        //生成深交所本月费用预估信息excel
        if (CollectionUtil.isNotEmpty(sourceSzItemsList)) {
            //解决jpa一级缓存自动更新的问题
            List<TradeSeatFeesItem> szItemsList = Lists.newArrayList();
            for (TradeSeatFeesItem tradeSeatFeesItem : sourceSzItemsList) {
                TradeSeatFeesItem tradeSeatFeesItem1 = new TradeSeatFeesItem();
                BeanUtils.copyProperties(tradeSeatFeesItem, tradeSeatFeesItem1);
                szItemsList.add(tradeSeatFeesItem1);
            }


            Map<String, List<TradeSeatFeesItem>> map = szItemsList.stream().collect(Collectors.groupingBy(TradeSeatFeesItem::getTradeSeatCode));
            List<TradeSeatFeesItem> resList = Lists.newArrayList();

            for (String tradeSetCode : map.keySet()) {
                List<TradeSeatFeesItem> items = map.get(tradeSetCode);
                if (CollectionUtil.isNotEmpty(items)) {
                    if (items.size() > 1) {
                        items = items.stream().sorted(Comparator.comparing(TradeSeatFeesItem::getId)).collect(Collectors.toList());
                        TradeSeatFeesItem firstItem = items.get(items.size() - 1);
                        TradeSeatFeesItem lastItem = items.get(0);
                        if (!DateUtil.format(firstItem.getDataDate(), DATE_YYYY_MM).equals(DateUtil.format(lastItem.getDataDate(), DATE_YYYY_MM))) {
                            if (Objects.nonNull(firstItem.getTradingOfferYearAmount())) {
                                firstItem.setTradingOfferYearAmount(firstItem.getTradingOfferYearAmount() - (Objects.nonNull(lastItem.getTradingOfferYearAmount()) ? lastItem.getTradingOfferYearAmount() : 0));
                            }

                            if (Objects.nonNull(firstItem.getNoneTradingOfferYearAmount())) {
                                firstItem.setNoneTradingOfferYearAmount(firstItem.getNoneTradingOfferYearAmount() - (Objects.nonNull(lastItem.getNoneTradingOfferYearAmount()) ? lastItem.getNoneTradingOfferYearAmount() : 0));
                            }
                            resList.add(firstItem);
                        }
                    } else {
                        resList.add(items.get(0));
                    }
                }
            }
            List<TradeSeatFeesDto> contentList = TradeSeatFeesMapper.INSTANCE.domain2dto(convertFees4Item(resList));

            addFlowSpeed(contentList);
            for (TradeSeatFeesDto tradeSeatFeesDto : contentList) {
                tradeSeatFeesDto.setChargeBeginDate(localDateTime.with(TemporalAdjusters.firstDayOfMonth()));
                tradeSeatFeesDto.setChargeEndDate(localDateTime.with(TemporalAdjusters.lastDayOfMonth()));
                calculateFeesItemNew("sh", tradeSeatFeesDto);
            }

            File emailFile = createEmailFile("深交所交易单元费用预估-本月.xlsx", ReportFileConfigEnum.TRADE_SEAT_FEES_EXPORT_AM_MONTH,
                    convertTradeSeatFeesEmailMonthDto(contentList));
            attachmentList.add(emailFile);
        }

        String emailId = mailService.sendMail(recvMailList, null, title, content, attachmentList);
        return emailId;
    }

    public void addFlowSpeed(List<TradeSeatFeesDto> contentList) {
        if (CollectionUtil.isEmpty(contentList)) {
            return;
        }

        List<String> codeList = contentList.stream().map(TradeSeatFeesDto::getTradeSeatCode).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(codeList)) {
            List<TradeSeatFlowSpeed> tradeSeatFlowSpeeds = tradeSeatFlowSpeedRepository.listByTradeSeatCode(codeList);
            if (CollectionUtil.isNotEmpty(tradeSeatFlowSpeeds)) {
                Map<String, TradeSeatFlowSpeed> flowSpeedMap = tradeSeatFlowSpeeds.stream().collect(Collectors.toMap(TradeSeatFlowSpeed::getTradeSeatCode, e -> e, (i, j) -> j));
                for (TradeSeatFeesDto e : contentList) {
                    TradeSeatFlowSpeed speed = flowSpeedMap.get(e.getTradeSeatCode());
                    if (Objects.nonNull(speed)) {
                        e.setFlowSpeedWeight(speed.getFlowSpeedWeight());
                    }
                }
            }
        }

    }

    private List<TradeSeatFeesEmailDto> convertTradeSeatFeesEmailDto(List<TradeSeatFeesDto> list) {
        if (CollectionUtil.isEmpty(list)) {
            return Lists.newArrayList();
        }

        List<TradeSeatFeesEmailDto> res = Lists.newArrayList();
        for (TradeSeatFeesDto tradeSeatFeesDto : list) {
            //有一个交易单元393476需要屏蔽下，性质属于股票质押专户，就别发了吧
            if ("393476".equals(tradeSeatFeesDto.getTradeSeatCode())) {
                continue;
            }
            TradeSeatFeesEmailDto tradeSeatFeesEmailDto = new TradeSeatFeesEmailDto();
            BeanUtils.copyProperties(tradeSeatFeesDto, tradeSeatFeesEmailDto);
            res.add(tradeSeatFeesEmailDto);
        }
        return res;
    }

    private List<TradeSeatFeesEmailMonthDto> convertTradeSeatFeesEmailMonthDto(List<TradeSeatFeesDto> list) {
        if (CollectionUtil.isEmpty(list)) {
            return Lists.newArrayList();
        }
        List<TradeSeatFeesEmailMonthDto> res = Lists.newArrayList();
        for (TradeSeatFeesDto tradeSeatFeesDto : list) {
            //有一个交易单元393476需要屏蔽下，性质属于股票质押专户，就别发了吧
            if ("393476".equals(tradeSeatFeesDto.getTradeSeatCode())) {
                continue;
            }
            TradeSeatFeesEmailMonthDto tradeSeatFeesEmailDto = new TradeSeatFeesEmailMonthDto();
            BeanUtils.copyProperties(tradeSeatFeesDto, tradeSeatFeesEmailDto);
            res.add(tradeSeatFeesEmailDto);
        }
        return res;
    }

    private List<TradeSeatFeesExportDto> convertFees(List<TradeSeatFees> feeList) {
        List<TradeSeatFeesExportDto> resList = Lists.newArrayList();
        for (TradeSeatFees tradeSeatFees : feeList) {
            TradeSeatFeesExportDto dto = new TradeSeatFeesExportDto();
            BeanUtils.copyProperties(tradeSeatFees, dto);
            resList.add(dto);
        }
        return resList;
    }

    private List<TradeSeatFees> convertFees4Item(List<TradeSeatFeesItem> feeItemList) {
        List<TradeSeatFees> resList = Lists.newArrayList();
        for (TradeSeatFeesItem tradeSeatFees : feeItemList) {
            TradeSeatFees dto = new TradeSeatFees();
            BeanUtils.copyProperties(tradeSeatFees, dto);
            resList.add(dto);
        }
        return resList;
    }


    private File createEmailFile(String fileName, ReportFileConfigEnum type, Object datas) {
        FileOutputStream fos = null;
        File file = new File(fileName);
        try {
            fos = new FileOutputStream(file);
            byte[] export = ReportFileUtil.export(datas, type);
            fos.write(export);
        } catch (Exception e) {
            log.error("创建资管子交易单元费用预估邮件异常", e);
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                log.error("创建资管子交易单元费用预估邮件关闭流异常", e);
            }
        }
        return file;
    }


    /**
     * file 转换为 MultipartFile
     *
     * @param file
     * @return
     */
    private MultipartFile convertMultipartFile(File file) {
        FileInputStream fileInputStream = null;
        MultipartFile multipartFile = null;
        try {
            fileInputStream = new FileInputStream(file);
            multipartFile = new MockMultipartFile(file.getName(), file.getName(),
                    ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return multipartFile;
    }

    private String convertBeginDate(String tradeSeatMarket, String beginDate) {
        LocalDate currentDate = LocalDate.now();
        int currentYear = currentDate.getYear();
        int previousYear = currentYear - 1;
        if (StringUtils.isBlank(beginDate)) {
            if (tradeSeatMarket.equals("sh")) {
                return previousYear + "-12-01";
            } else if (tradeSeatMarket.equals("sz")) {
                return previousYear + "-12-01";
            }
        } else {
            return beginDate;
        }
        return null;
    }

    private LocalDateTime convertBeginLocalDateTime(String tradeSeatMarket, String beginDate) {
        if (Objects.isNull(beginDate)) {
            return DateUtil.parseLocalDateTime(convertBeginDate(tradeSeatMarket, null), DATE_YYYY_MM_DD);
        }
        beginDate = beginDate.substring(0, 10);
        String begin = convertBeginDate(tradeSeatMarket, null);
        if (DateUtil.parseLocalDateTime(begin, DATE_YYYY_MM_DD).isAfter(DateUtil.parseLocalDateTime(beginDate, DATE_YYYY_MM_DD))) {
            return DateUtil.parseLocalDateTime(begin, DATE_YYYY_MM_DD);
        }
        return DateUtil.parseLocalDateTime(beginDate, DATE_YYYY_MM_DD);
    }

    private String convertEndDate(String tradeSeatMarket, String endDate) {
        LocalDate currentDate = LocalDate.now();
        int currentYear = currentDate.getYear();
        if (StringUtils.isBlank(endDate)) {
            if (tradeSeatMarket.equals("sh")) {
                return currentYear + "-11-30";
            } else if (tradeSeatMarket.equals("sz")) {
                return currentYear + "-11-30";
            }
        } else {
            return endDate;
        }
        return null;
    }

    /**
     * 返回指定月份的第一天
     *
     * @param beginDate
     * @return
     */
    private String convertBeginDateNew(LocalDateTime beginDate) {
        if (Objects.nonNull(beginDate)) {
            return DateUtil.format(beginDate.with(TemporalAdjusters.firstDayOfMonth()), DATE_YYYY_MM_DD);
        }
        return null;
    }

    /**
     * 返回指定月份的最后一天
     *
     * @param endDate
     * @return
     */
    private String convertEndDateNew(LocalDateTime endDate) {
        if (Objects.nonNull(endDate)) {
            return DateUtil.format(endDate.minusMonths(1).with(TemporalAdjusters.lastDayOfMonth()), DATE_YYYY_MM_DD);
        }
        return null;
    }


    private Page<TradeSeatFeesDto> domainToDto(Page<TradeSeatFees> ret, Pageable pageable) {
        Page<TradeSeatFeesDto> page;
        if (null != ret && ret.getNumberOfElements() > 0) {
            List<TradeSeatFeesDto> contentList = TradeSeatFeesMapper.INSTANCE.domain2dto(ret.getContent());
            page = new PageImpl(contentList, pageable, ret.getTotalElements());
        } else {
            page = new PageImpl(new ArrayList(), pageable, ret.getTotalElements());
        }
        return page;
    }


}
